﻿#define _CRT_SECURE_NO_WARNINGS
// ↑ 将本行在代码放在第一行可以避免 scanf的报错问题（仅在VS编译器里）
//【入门】2.类和对象(1)



//【头文件包含】
//C++的主要头文件
#include<iostream>//c++的输入输出流
using std::cout, std::endl;

#include<map>
//C的主要头文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h> 




//【命名空间】


//【结构体声明】

//【类声明】
class Person
{
public:
	void Print()//类的方法：成员函数
	{
		cout << _name << "-" << _age << "-" << _password<<endl;
	}
	/*void _InfoInput(Person* ip,char* name, int age, char* password)
	{
		ip->_age = age;
		strcpy(ip->_name, name);
		strcpy(ip->_password, password);
	}*/
	void _InfoInput(char* name, int age, char* password)
	{
		_age = age;
		strcpy(_name, name);
		strcpy(_password, password);
	}
private:
	char _name[10];//类的属性：成员变量
	int _age;
protected:
	char _password[20];
};

 
//【函数声明】
void Test1();
void Test2();
void swap_c(int*p1,int*p2); void swap_cpp(int & p1,int & p2);
int count1(); int& count2();
inline int Add(int left, int right);
//【主函数】
int main()
{
	Test1();
	Test2();
	return 0;
}

//【函数定义】
/*引用作参数-C语言实现值交换*/void swap_c(int* p1, int* p2)
{
	int tmp = *p1;
	*p1=*p2;
	*p2 = tmp;
}
/*引用作参数-C++语言实现值交换*/void swap_cpp(int& p1, int& p2)
{
	int tmp = p1;
	p1 = p2;
	p2 = tmp;
}

/*引用作返回值-传值返回*/int count1()
{
	static int n = 0;
	n++;
	return n;
}
/*引用做返回值-传引用返回*/int&count2()
{
	static int n2 = 0;
	n2++;
	return n2;
}

/**/inline int Add(int left, int right)
{
	return left + right;
}

/*测试用例*/void Test1()
{
	printf("****测试用例开始****\n");
	//引用作参数
	const int a = 10;
	int b = a;
	int c = 1;
	printf("b=%d c=%d\n", b, c);
	swap_c(&b, &c);
	printf("b=%d c=%d\n", b, c);
	swap_cpp(b, c);
	cout <<"b=" << b << " c=" << c << endl;
	//引用作返回值
	int m1 = count1();
	int m2 = count2();
	int &m2_ = count2();
	count1(); count2();
	printf("%d %d %d\n", m1, m2,m2_);
	//内联函数
	int sum = Add(1, 2);
	printf("%d\n", sum);
	//关键字：auto（推导 )
	int n = 123;
	auto m = n;
	cout << typeid(n).name() << endl;
	cout << typeid(m).name() << endl;
	//基于范围的for循环
	int arr[] = { 1,2,3,4,5,6 };
		//将数组中的值乘二倍再打印一遍
	for (auto e : arr)
	{
		e *= 2;
	}
	for (auto e : arr)
	{
		cout << e << " ";
	}
	cout << endl;
	for (auto& e: arr)
	{
		e *= 2;
	}
	for (auto e : arr)
	{
		cout << e << " ";
	}
	cout << endl;

	printf("****测试用例结束****\n\n");
}


/*测试用例*/void Test2()
{
	printf("****测试用例开始****\n");
	Person p1,p2;
	char p1name[] = "Yang";
	char p1password[] = "123456";
	char p2name[] = "Yan";
	char p2password[] = "12345";
	p1._InfoInput(p1name, 30, p1password);
	p1.Print();
	p2._InfoInput(p2name, 29, p2password);
	p2.Print();
	

	printf("****测试用例结束****\n\n");
}


//【笔记】
//【入门】2.类和对象(1)
	//引用的一些用法
		//引用作参数，可以替代C语言中的传参数的指针，以Swap为例c++的引用方式占用空间更少 
		//引用作返回值，作为返回值时返回的是值的别名可以利用引用值接收也可以用新的变量空间接收，
			//引用做返回值在运行时更高效，但是存在安全隐患，需配合static的静态变量来使用，保证函数内变量作用域扩大至整个工程
	//内联函数
		//在频繁调用一些函数时是会造成过多栈帧的性能消耗// C语言中通过使用宏函数来避免// C++中则通过内敛函数来解决
		//在函数前加 inline 实现内联函数，该函数会在调用位置直接展开，
		//内联函数是利用空间换时间，即展开时会生成更多变量，空间复杂度会提高，如果内敛函数内容过多，编译器可能会不将其视为内敛函数，不展开
		//内敛函数的声明和定义不能分开
		//c++中建议用 const int n 来替代宏define n；建议用内敛函数替代宏函数
	//关键字：auto（推导 )
		// auto 可以根据变量赋值的类型推导变量的格式，
		//推导不可以作为函数参数、不能直接声明数组，不能同时推导两个不同类型的值
	//基于范围的for循环
		// 可以在利用for遍历数组时简化写法，但要用一个引用值接收
		// 同时不能再函数参数为数组时使用，因为数组在传参时会退化为指针
	//C++中的空指针写法：建议将NULL替换为nullptr，因为C++中可能会把NULL定义为0的字面常量
	//面向对象:有三大特性 封装、继承、多态
		//C语言是面向过程的语言|C++是面向对象的语言
		//C语言的结构体只能定义变量
		//类：包含类的属性、类的方法，其中//类的属性：成员变量//类的方法：成员函数
			//C++的结构体还可以定义函数，实际上C++中的结构体可以叫作类class |同时也可以用struct
			//定义类时建议成员名前加下划线_
		//类的成员函数
			//在定义类的成员函数时，一般工程是将函数声明和函数定义分离
			//如果函数定义和声明都在类里，则类里的函数视为内敛函数
		//类的封装
			//类可以通过封装实现类的成员按适当的权限对外进行交互 public: 为公有|private: 为私有 |ptrotected:为保护
			// struct的成员默认为公有 class的成员默认为私有



